
#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <unistd.h>
#include <string.h>
using namespace std;

const uint16_t g_port = 8080;

class tcpServer
{
private:
    int _socket;
public:
    tcpServer()
    {}
    ~tcpServer()
    {}
    void Init()
    {
        //1. 创建socket
        _socket = ::socket(AF_INET,SOCK_STREAM,0);
        if(_socket < 0)
        {
            cout << "1. create socket fail" << endl;
            return;
        }
        cout << "create socket success,socket:" << _socket << endl;
        //2 .绑定
            //2.1设置
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family = AF_INET;
        local.sin_addr.s_addr = INADDR_ANY;
        local.sin_port = ::htons(g_port);

            //2.2绑定
        int n = ::bind(_socket,(sockaddr*)&local,sizeof(local));
        if(n < 0)
        {
            cout << "2. bind socket fail" << endl;
            return;
        }
        cout << "bind socket success,socket:" << _socket << endl;

        //3. 监听
        n = ::listen(_socket,4);
        if(n < 0)
        {
            cout << "3. listen fail" << endl;
            return;
        }
        cout << "listen success" << endl;
    }
    void Start()
    {
        while(true)
        {
            struct sockaddr_in from;    //用来存放接受连接的客户端的地址信息
            socklen_t len = sizeof(from);
            //获取客户端的数据（sockfd） + 信息(accept 的参数获得)

            //_Socket正在监听的socket     （拉客的）
            //返回值是一个socket,即所接待的人的fd (接待的服务员)
            int fd = ::accept(_socket,(sockaddr*)&from,&len);
            if(fd < 0)
            {
                cout << "accept fail" << endl;
                continue;
            }
            cout << "accept success,fd:" << fd << endl;
            //version1，单执行流
            // HandleTask(fd);

            //version2,多进程
            pid_t id = fork();
            if(id == 0)
            {
                //1. 子进程关闭不需要的文件描述符
                close(_socket);
                HandleTask(fd);
                exit(0);
            }
            //父进程关闭fd(它不关心这个文件描诉符表了，已经继承给子进程处理了)
            close(fd);
            int rid = waitpid(id,nullptr,0);
            if(rid < 0)
            {
                cout << "waitpid error" << endl;
            }
        }
    }

    void HandleTask(int fd)
    {
        char buffer[2048];
        while(true)
        {
            //从指定的fd中读取
            int n = ::read(fd,buffer,sizeof(buffer));
            if(n > 0)
            {
                buffer[n] = 0;
                cout << buffer << endl;

                string message = "echo# ";
                message += buffer;
                //返回给发送者
                write(fd,message.c_str(),message.size());
            }
            else if(n == 0)
            {
                cout << "client quit,fd:" << fd<< endl;
                break;
            }
            else
                break;
        }
        close(fd);
    }
};